package com.sky.service.common.impl;

import com.alibaba.fastjson.JSON;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.admin.MerchantMapper;
import com.sky.mapper.courier.CourierMapper;
import com.sky.mapper.courier.CourierTradeOrderMapper;
import com.sky.mapper.user.OrderMapper;
import com.sky.pojo.Courier;
import com.sky.pojo.CourierTradeOrder;
import com.sky.pojo.Merchant;
import com.sky.pojo.Orders;
import com.sky.service.common.OrderDispatchService;
import com.sky.utils.MapUtils;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderDispatchServiceImpl implements OrderDispatchService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private CourierMapper courierMapper;

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private CourierTradeOrderMapper courierTradeOrderMapper;

    /**
     *
     * @param orderId   商家接单时，传递此参数
     * @param tradeNo   骑手拒单时，传递该参数
     * @param courerId  骑手拒单时，传递该参数
     * @return
     */
    @Override
    public Courier dispatch(Long orderId,Long tradeNo,Long courerId) {

        Orders orders = null;
        //如果是转单，order应该通过tradeNo去获取
        //转单
        if(tradeNo!=null) {
            orders = orderMapper.selectOrdersByTradeNo(tradeNo);
        }
        else{
            orders = orderMapper.getById(orderId);
        }


        if(orders==null){
            throw new OrderBusinessException("订单不存在");
        }
        //1.找骑手
//        1.优先查询商家10公里内的在职骑手  -- 多个骑手
        List<Courier> courierList = findCourierNearMerchant(orders.getShopId());
        //剔除当前骑手
        if(courerId!=null){
            courierList = courierList.stream().filter(courier -> {
                return courier.getId()!=courerId;
            }).collect(Collectors.toList());
        }

        if(courierList==null||courierList.size()==0){
            return null;
        }
        List<Long> courierIds = courierList.stream().map(courier -> {
            return courier.getId();
        }).collect(Collectors.toList());
//        2.然后考虑上述骑手中，订单量最少的骑手 -- 找出指定骑手的当日接单量
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        /*
            返回值：
            [
                {id:2,total:23},
                {id:3,total:23}
            ]
         */
        List<Map<String,Long>> mapList = courierTradeOrderMapper.findTodayOrdersNumByIds(courierIds,today);
        //找最小值
        Long minNum = mapList.stream().min(Comparator.comparing(map -> {
            return map.get("total");
        })).get().get("total");
//        3.找出最小订单相近的骑手（3单以内）  -- 比如最小订单数是10，那么找出订单量10,11,12,13的骑手   --多个骑手
        courierIds = mapList.stream().filter(map -> {
            return map.get("total") <= minNum + 3;
        }).map(map -> {
            return map.get("id");
        }).collect(Collectors.toList());
//        4.骑手的待接单和已接单（骑手正在进行中的订单）不能超过12
        courierIds  = courierTradeOrderMapper.findTodayOrdersLessThen12ByIds(courierIds,today);
//        5.按照上述规则条件如果没有找到，从最初的10公里内的骑手中随机挑选一个
        if(courierIds.size()==0){
            int index = new Random().nextInt(courierList.size());
            courierIds.add(courierList.get(index).getId());
        }
//      6.然后从所有满足条件的骑手中，找到评分最高的做为最终骑手进行派单
        List<Long> courierIds2 = courierIds;
        //先从10公里内进行提取骑手，按照评分排序降序排列，取第一个。
        Courier finalCourier = courierList.stream().filter(courier -> {
            return courierIds2.contains(courier.getId());
        }).sorted(Comparator.comparing(Courier::getScore).reversed())
        .collect(Collectors.toList()).get(0);
        //2.生成运单，入库
        saveCourierTradeOrder(orders,finalCourier,tradeNo);
        //3.通知骑手 （后面实现）
        notifyCourier(orders.getNumber(),finalCourier.getId());

        return finalCourier;
    }

    @Autowired
    private WebSocketServer webSocketServer;

    public void notifyCourier(String orderNumber,Long courerId){
        //构建信息
        Map<String,Object> map = new HashMap<>();
        map.put("tradeNo",orderNumber);
        map.put("code",1);
        map.put("msg","您有新的待接单,请及时查收！");
        String message = JSON.toJSONString(map);

        //发送
        webSocketServer.sendRiderInfo(message,courerId);
    }

    private void saveCourierTradeOrder(Orders orders, Courier finalCourier,Long tradeNo) {


        //判断是否是转单操作，如果是转单，直接修改运单所对应的courer_id即可
        if(tradeNo!=null){
            //说明是转单操作
            courierTradeOrderMapper.updateCourierIdByTradeNo(finalCourier.getId(),tradeNo);

            return;
        }


        Merchant merchant = merchantMapper.selectById(orders.getShopId());

        //计算提成
        /**
         * - 1 公里内                  3块    取5成
         * - 超出1公里部分 少于3公里部分  3-5   取6成
         * - 超出3公里部分  0.7         >5    取7成
         *    公里数换算成配送费
         */
        double deliveryFee = orders.getDeliveryFee().doubleValue();
        BigDecimal courierCost = null;
        if(deliveryFee<=3){
            courierCost = BigDecimal.valueOf(1.5);
        }else if(deliveryFee>3&&deliveryFee<=5){
            courierCost = BigDecimal.valueOf(1.5);; // 基础费用
            BigDecimal otherCost =BigDecimal.valueOf(deliveryFee-3).multiply(BigDecimal.valueOf(0.6)); //介于3到5块之前，取6成
            courierCost = courierCost.add(otherCost);
        }else if(deliveryFee>5){
            courierCost = BigDecimal.valueOf(1.5);// 基础非
            BigDecimal other1Cost = BigDecimal.valueOf(1.2); //介于1到3公里之间的费用
            BigDecimal endCost = BigDecimal.valueOf(deliveryFee-5).multiply(BigDecimal.valueOf(0.7));
            courierCost = courierCost.add(other1Cost);
            courierCost = courierCost.add(endCost);
        }

        //构建运单对象
        CourierTradeOrder courierTradeOrder = CourierTradeOrder
                                            .builder()
                                            .totalAmount(orders.getAmount())
                                            .courierId(finalCourier.getId())
                                            .orderNumber(orders.getNumber())
                                            .waybillStatus(CourierTradeOrder.DISPATCH_OK)
                                            .tradeCreateTime(LocalDateTime.now())
                                            .shopAddress(merchant.getShopAddress())
                                            .remark(orders.getRemark())
                                            .customerName(orders.getConsignee())
                                            .customerAddress(orders.getAddress())
                                            .customerExpectedDeliveryTime(orders.getEstimatedDeliveryTime())
                                            .shopName(merchant.getShopName())
                                            .toBeMealTime(orders.getMealTime())
                                            .telephone(orders.getPhone())
                                            .income(courierCost)
                                            .build();

        //保存到数据库
        courierTradeOrderMapper.save(courierTradeOrder);
    }


//    private List<Courier> findCourierNearMerchant(Long shopId) {
//
//        Merchant merchant = merchantMapper.selectById(shopId);
//        //116.310442,40.056564
//        String shopGeo = MapUtils.addressToLnglat(merchant.getShopAddress());
//        //1 查询在职的骑手
//        List<Courier> courierList = courierMapper.findAllCourierOnJob();
//
//        //2.将距离商家超过10公里的骑手排除在外即可
//        /**      高德驾车距离     高德直线距离       redis的测距    mysql8.0测距和上述一致，基本没误差
//         *   5   1043           497.0            497.6430
//         *   6   1749.0         640             639.6959
//         *   7   864.0-         311             311.5427
//         *   8   1064.0         517             517.3018
//         */
//        //2.将距离商家超过10公里的骑手排除在外即可
//        courierList = courierList.stream().filter(courier -> {
//            double distance = MapUtils.calculateDistance2(shopGeo, courier.getCurLocation());
//            System.out.println(distance+"----"+courier.getId());
//            return distance<10000;
//        }).collect(Collectors.toList());
//
//        //  return courierList;
//        return null;
//    }

    @Autowired
    private RedisTemplate redisTemplate;
    private List<Courier> findCourierNearMerchant(Long shopId) {

        Merchant merchant = merchantMapper.selectById(shopId);
        //116.310442,40.056564
        String shopGeo = MapUtils.addressToLnglat(merchant.getShopAddress());
        String[] lnglat = shopGeo.split(",");
        // 以经纬度为中心，获取半径不超过最大距离的所有元素
        Point point = new Point(Double.parseDouble(lnglat[0]),Double.parseDouble(lnglat[1]));
        // 半径为10km
        Distance distance = new Distance(10, RedisGeoCommands.DistanceUnit.KILOMETERS);
        Circle circle = new Circle(point, distance);

        List<Long> courierIds = new ArrayList<>();
        GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate.opsForGeo().radius("location2",circle);
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = results.getContent();
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult:content){
            RedisGeoCommands.GeoLocation<Object> geoResultContent = geoResult.getContent();
            System.out.println("名字:"+geoResultContent.getName());

            String idStr = geoResultContent.getName().toString().split("_")[1];
            courierIds.add(Long.parseLong(idStr));
        }
        //根据骑手的id查询骑手信息
        List<Courier> courierList = courierMapper.findCourierByIds(courierIds);

        //  return courierList;
        return courierList;
    }



}
